package main

import (
	"global/structs"
	"github.com/garyburd/redigo/redis"
	"github.com/ngaut/log"
	"global/function"
)

//
func rebuildRedisData(context *Context, results *structs.Results, coinPair string) {

	conn := context.GetOteRedis().Get()
	if conn == nil {
		log.Errorf("redis conn pool return nil, please check.")
	}
	defer conn.Close()

	// order 记录
	doRollbackHistoryOrders(conn, coinPair, len(results.OrderLogs))

	// 撤销用户历史成交记录
	doRollbackHistoryUserOrders(conn, coinPair, results.OrderLogs)

	// 撤销已完成的单子记录
	doRollbackFinishedTrustCoins(conn, coinPair, results)

	// 重塑主动单
	if _, err := rebuildOneUserData(conn, coinPair, results.ActiveTrust.OriginalTrustCoin); err != nil {
		// 主动单回溯失败的情况
		log.Errorf("active trust rebuild to redis failed, msg: %s", err.Error())
	}
	log.Infof("rebuild active trust data success, tid: %d", results.ActiveTrust.TrustId)

	// 重塑被动单
	for _, t := range results.PassiveTrusts {
		if _, err := rebuildOneUserData(conn, coinPair, t.OriginalTrustCoin); err != nil {
			log.Errorf("passive rebuild to redis failed, tid: %d, msg: %s", t.TrustId, err.Error())
		}
		log.Infof("rebuild passive trust data success, tid: %d, uid: %d, status: %d", t.TrustId, t.Uid, t.TrustDealStatus)
	}
}

func doRollbackFinishedTrustCoins(conn redis.Conn, coinPair string, results *structs.Results) {
	// 主动单
	if results.ActiveTrust.TrustDealStatus == structs.TRUST_STATUS_ALL {
		conn.Do("LPOP", function.GetUserHistoryTrustKey(coinPair, results.ActiveTrust.Uid))
		conn.Do("LPOP", function.GetUserHistoryTrustWithoutCoinPairKey(results.ActiveTrust.Uid))
	}

	for _, t := range results.PassiveTrusts {
		if t.TrustDealStatus == structs.TRUST_STATUS_ALL {
			conn.Do("LPOP", function.GetUserHistoryTrustKey(coinPair, t.Uid))
			conn.Do("LPOP", function.GetUserHistoryTrustWithoutCoinPairKey(t.Uid))
		}
	}
}

func doRollbackHistoryUserOrders(conn redis.Conn, coinPair string, orders []*structs.OrderLogs) {
	for _, o := range orders {
		// 买家
		orderBuyKey := function.GetUserOrdersKey(coinPair, o.Order.BuyUid)
		conn.Do("LPOP", orderBuyKey)

		// 卖家
		orderSaleKey := function.GetUserOrdersKey(coinPair, o.Order.SaleUid)
		conn.Do("LPOP", orderSaleKey)
	}
}

func doRollbackHistoryOrders(conn redis.Conn, coinPair string, length int) {
	orderKey := function.GetOrderKey(coinPair)
	for i:=0; i<length; i++ {
		conn.Do("LPOP", orderKey)
	}
}

func rebuildOneUserData(conn redis.Conn, coinPair string, coin *structs.TrustCoin) (bool, error) {
	conn.Send("MULTI")
	if _, err := updateTrustAndUserDetailAndWithMulti(
		conn,
		coinPair,
		structs.TaskType(coin.Flag),
		coin.Id,
		coin.Uid,
		coin); err != nil {
		log.Errorf("Rebuild: add user and detail failed: msg: %s, %v", err.Error(), coin)
		conn.Do("DISCARD")
		return false, err
	}
	log.Infof("Rebuild: add user and detail success, tid: %d", coin.Id)

	_, err := addTrustToWaitWithMulti(
		conn,
		structs.TaskType(coin.Flag),
		coinPair,
		coin.Id,
		coin.Price)
	if err != nil {
		log.Errorf("Rebuild: add trust to wait failed, err: %s", err.Error())
		conn.Do("DISCARD")
		return false, err
	}
	log.Infof("Rebuild: add trust to wait success, tid: %d", coin.Id)
	conn.Do("EXEC")
	return true, nil
}



